/*
** Copyright (C) 2011 Viens Yann
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <algorithm>
#include "Singleton.hpp"
#include "GameBombCatcher.hpp"
#include "Variables.hpp"
#include "Deletor.hpp"
#include "Drawer.hpp"
#include "CollisionsChecker.hpp"

GameBombCatcher::GameBombCatcher()
{
  _detector = Singleton<ObjectDetector>::instance();
  _life = 10;
}

GameBombCatcher::~GameBombCatcher()
{
  Deletor	deletor;

  _rockets.remove_if(deletor);
}

IplImage*	GameBombCatcher::gameAction(IplImage* input) throw (LevelError)
{
  if (_launched)
    {
      if (_racket.getSize()._x == -1 && _racket.getSize()._y == -1)
	{
	  initRacket(input->width, input->height);
	}
      checkCollisions();
      event(input);
      move();
      rocketApparitions();
      draw(input);
      return input;
    }
  else
    return input;
}

void		GameBombCatcher::start()
{
  _launched = true;
  _score = 0;
  _life = 10;
  _startDate = time(0);
  initRacket();

}

void		GameBombCatcher::stop()
{
  _launched = false;

  Deletor	deletor;
  _rockets.remove_if(deletor);
}

void		GameBombCatcher::initRacket(const int width, const int height)
{
  if (width == -1 && height == -1)
    {
      _racket.setPos(-1, -1);
      _racket.setDir(-1, -1);
      _racket.setSize(-1, -1);
    }
  else
    {
      _racket.setSize(width / 5, 10);
      _racket.setPos((width / 2), height - height / 10);
      _racket.setDir((width / 2), height - height / 10);
    }
}

void		GameBombCatcher::rocketApparitions()
{
  if (rand() % 5 == 0)
    _rockets.push_back(new Rocket());
}

void		GameBombCatcher::checkCollisions()
{
  CollisionsChecker	checker(_racket, _score);

  _rockets.remove_if(checker);
}

void		GameBombCatcher::event(IplImage* input)
{
  CvRect*	result = _detector->detect(input);

  if (result)
    {
      cvRectangle(input, cvPoint(result->x, result->y), cvPoint(result->x + result->width, result->y + result->height), cvScalar(0, 0, 255));
      _racket.setPos(result->x + (result->width / 2) - (_racket.getSize()._x / 2), _racket.getPos()._y);
    }
}

void		GameBombCatcher::move()
{
  Mover		mover(_life);

  _rockets.remove_if(mover);
}

void		GameBombCatcher::draw(IplImage* screen)
{
  Drawer	drawer(screen);

  std::for_each(_rockets.begin(), _rockets.end(), drawer);
  _racket.draw(screen);
}

GameBombCatcher::Mover::Mover(int& life): _life(life)
{
}

bool	GameBombCatcher::Mover::operator()(Rocket* item)
{
  item->move();
  if (item->getPos()._y >= camZoneHeight)
    {
      _life--;
      delete item;
      return true;
    }
  return false;
}
